import { BooleanProperty, ESJFlyInParam, ESJFlyToParam, ESJPickedInfo, ESPropertiesType, FunctionProperty, GroupProperty, JsonProperty, NumberProperty, Property, StringProperty } from "@/ESJTypes";
import { Event, extendClassProps, Listener, reactJsonWithUndefined, UniteChanged } from "xbsj-base";
import { ESSceneObject } from "./ESSceneObject";

export abstract class ESVisualObject extends ESSceneObject {

    private _flyInEvent = this.dv(new Event<[duration: number]>());
    get flyInEvent(): Listener<[duration: number]> { return this._flyInEvent; }
    flyIn(duration: number = 1) { this._flyInEvent.emit(duration); }

    private _flyToEvent = this.dv(new Event<[duration: number]>());
    get flyToEvent(): Listener<[duration: number]> { return this._flyToEvent; }
    flyTo(duration: number = 1) { this._flyToEvent.emit(duration); }

    private _pickedEvent = this.dv(new Event<[ESJPickedInfo]>());
    get pickedEvent() { return this._pickedEvent; }

    private _calcFlyToParamEvent = this.dv(new Event());
    get calcFlyToParamEvent(): Listener { return this._calcFlyToParamEvent; }
    calcFlyToParam() { this._calcFlyToParamEvent.emit(); }

    private _calcFlyInParamEvent = this.dv(new Event());
    get calcFlyInParamEvent(): Listener { return this._calcFlyInParamEvent; }
    calcFlyInParam() { this._calcFlyInParamEvent.emit(); }

    emptyFlyToParam() { this.flyToParam = undefined; }
    emptyFlyInParam() { this.flyInParam = undefined; }

    /**
     * 是否使用ESObjectWithLocation类中的calcFlyToParam
     */
    public useCalcFlyToParamInESObjectWithLocation = false;

    static override defaults = {
        ...ESSceneObject.defaults,
        show: true,
        collision: true,
        allowPicking: false,
        flyToParam: { distance: 0, heading: 0, pitch: 0, flyDuration: 1, hDelta: 0, pDelta: 0 } as ESJFlyToParam,
        flyInParam: { position: [0, 0, 0], rotation: [0, 0, 0], flyDuration: 1 } as ESJFlyInParam,
    };
    getESProperties() {
        return {
            basic: [],
            general: [
                new StringProperty('唯一标识', 'id', false, true, [this, 'id']),
                new StringProperty('名称', 'name', true, false, [this, 'name']),
                new BooleanProperty('是否显示', 'show', false, false, [this, 'show'], ESVisualObject.defaults.show),
                new BooleanProperty('开启碰撞', 'collision', false, false, [this, 'collision'], ESVisualObject.defaults.collision),
                new BooleanProperty('允许拾取', 'allowPicking', false, false, [this, 'allowPicking'], ESVisualObject.defaults.allowPicking),
                new FunctionProperty("保存观察视角", "保存当前flyToParam", [], () => this.calcFlyToParam(), []),
                new FunctionProperty("清空飞向参数", "清空飞向参数", [], () => this.emptyFlyToParam(), []),
                new FunctionProperty("清空飞入参数", "清空飞入参数", [], () => this.emptyFlyInParam(), []),
                new FunctionProperty('保存飞入参数', '保存飞入参数flyInParam', [], () => this.calcFlyInParam(), []),
            ],
            dataSource: [],
            location: [],
            coordinate: [],
            style: [],
        } as ESPropertiesType;
    };

    override getProperties(language?: string) {
        return [
            ...super.getProperties(language),
            new GroupProperty('ESVisualObject', 'ESVisualObject', [
                new BooleanProperty('是否显示', '是否显示.', false, false, [this, 'show'], ESVisualObject.defaults.show),
                new BooleanProperty('是否开启碰撞监测', 'collision,是否开启碰撞监测.', false, false, [this, 'collision'], ESVisualObject.defaults.collision),
                new BooleanProperty('是否允许拾取', '是否允许被鼠标点击拾取.', false, false, [this, 'allowPicking'], ESVisualObject.defaults.allowPicking),
                new GroupProperty('飞行定位', '飞向参数', [
                    new FunctionProperty("飞向", "飞向", ['number'], (duration: number) => this.flyTo(duration), [1]),
                    new JsonProperty('flyToParam', 'flyToParam', true, false, [this, 'flyToParam'], ESVisualObject.defaults.flyToParam),
                    new FunctionProperty("获取当前参数", "获取当前flyToParam", [], () => this.calcFlyToParam(), []),
                ]),
                new GroupProperty('飞入定位', '飞入参数', [
                    new FunctionProperty("飞入", "飞入", ["number"], (duration: number) => this.flyIn(duration), [1]),
                    new JsonProperty('flyInParam', 'flyInParam', true, false, [this, 'flyInParam'], ESVisualObject.defaults.flyInParam),
                    new FunctionProperty('获取当前相机参数', '获取当前相机参数', [], () => this.calcFlyInParam(), []),
                ]),
            ]),
        ];
    }
}

export namespace ESVisualObject {
    export const createDefaultProps = () => ({
        show: true,
        collision: true,
        allowPicking: false,
        flyToParam: reactJsonWithUndefined<ESJFlyToParam>(undefined),
        flyInParam: reactJsonWithUndefined<ESJFlyInParam>(undefined),
        ...ESSceneObject.createDefaultProps(),
    });
}
extendClassProps(ESVisualObject.prototype, ESVisualObject.createDefaultProps);
export interface ESVisualObject extends UniteChanged<ReturnType<typeof ESVisualObject.createDefaultProps>> { }
